/*
 * xlogutils.h
 *
 * 用于重放 WAL 记录的工具。
 *
 * Portions Copyright (c) 1996-2022, PostgreSQL Global Development Group
 * Portions Copyright (c) 1994, Regents of the University of California
 *
 * src/include/access/xlogutils.h
 */
#ifndef XLOG_UTILS_H
#define XLOG_UTILS_H

#include "access/xlogreader.h"
#include "storage/bufmgr.h"

/*
 * 在8.4之前，所有恢复期间的活动由启动过程执行。这个局部变量
 * 在代码的许多部分中继续使用，以指示RecoveryManagers所采取的行动。
 * 其他可能在恢复期间执行工作的进程应检查RecoveryInProgress()。
 * 详见xlog.c中的XLogCtl注释。
 */
extern PGDLLIMPORT bool InRecovery;

/*
 * 像 InRecovery 一样，standbyState 仅在启动过程中有效。
 * 在所有其他进程中，它将具有值 STANDBY_DISABLED（因此
 * InHotStandby 将读取为 false）。
 *
 * 在 DISABLED 状态下，我们正在执行崩溃恢复或热备份
 * 在 postgresql.conf 中被禁用。
 *
 * 在 INITIALIZED 状态下，我们已运行 InitRecoveryTransactionEnvironment，
 * 但尚未处理 RUNNING_XACTS 或 shutdown-checkpoint WAL 记录
 * 来初始化我们的主事务跟踪系统。
 *
 * 当事务跟踪初始化后，我们进入 SNAPSHOT_PENDING
 * 状态。跟踪的信息可能仍然不完整，因此我们尚不能允许
 * 连接，但 redo 函数必须在适当时更新内存状态。
 *
 * 在 SNAPSHOT_READY 模式下，我们完全了解在
 * 当前 WAL 位置上，主机上正在（或曾经）运行的事务。
 * 可以获取快照，并运行只读查询。
 */
typedef enum
{
	STANDBY_DISABLED,
	STANDBY_INITIALIZED,
	STANDBY_SNAPSHOT_PENDING,
	STANDBY_SNAPSHOT_READY
} HotStandbyState;

extern PGDLLIMPORT HotStandbyState standbyState;

#define InHotStandby (standbyState >= STANDBY_SNAPSHOT_PENDING)


extern bool XLogHaveInvalidPages(void);
extern void XLogCheckInvalidPages(void);

extern void XLogDropRelation(RelFileNode rnode, ForkNumber forknum);
extern void XLogDropDatabase(Oid dbid);
extern void XLogTruncateRelation(RelFileNode rnode, ForkNumber forkNum,
								 BlockNumber nblocks);

/* XLogReadBufferForRedo[Extended] 的结果代码 */
typedef enum
{
	BLK_NEEDS_REDO,				/* 需要应用的 WAL 记录中的更改 */
	BLK_DONE,					/* 块已是最新 */
	BLK_RESTORED,				/* 块是从完整页面图像恢复的 */
	BLK_NOTFOUND				/* 未找到块（因此不需要重放） */
} XLogRedoAction;

/* read_local_xlog_page_no_wait 回调的私有数据。 */
typedef struct ReadLocalXLogPageNoWaitPrivate
{
	bool		end_of_wal;		/* 当 WAL 结束时为真 */
} ReadLocalXLogPageNoWaitPrivate;

extern XLogRedoAction XLogReadBufferForRedo(XLogReaderState *record,
											uint8 buffer_id, Buffer *buf);
extern Buffer XLogInitBufferForRedo(XLogReaderState *record, uint8 block_id);
extern XLogRedoAction XLogReadBufferForRedoExtended(XLogReaderState *record,
													uint8 buffer_id,
													ReadBufferMode mode, bool get_cleanup_lock,
													Buffer *buf);

extern Buffer XLogReadBufferExtended(RelFileNode rnode, ForkNumber forknum,
									 BlockNumber blkno, ReadBufferMode mode,
									 Buffer recent_buffer);

extern Relation CreateFakeRelcacheEntry(RelFileNode rnode);
extern void FreeFakeRelcacheEntry(Relation fakerel);

extern int	read_local_xlog_page(XLogReaderState *state,
								 XLogRecPtr targetPagePtr, int reqLen,
								 XLogRecPtr targetRecPtr, char *cur_page);
extern int	read_local_xlog_page_no_wait(XLogReaderState *state,
										 XLogRecPtr targetPagePtr, int reqLen,
										 XLogRecPtr targetRecPtr,
										 char *cur_page);
extern void wal_segment_open(XLogReaderState *state,
							 XLogSegNo nextSegNo,
							 TimeLineID *tli_p);
extern void wal_segment_close(XLogReaderState *state);

extern void XLogReadDetermineTimeline(XLogReaderState *state,
									  XLogRecPtr wantPage,
									  uint32 wantLength,
									  TimeLineID currTLI);

extern void WALReadRaiseError(WALReadError *errinfo);

#endif
